<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>
<script>
    // 函数嵌套
    // function fn() {
    //     var a = 10; // 10 => 11
    //     console.log("a", a); // 10

    //     function func() {
    //         a++;
    //         console.log("a", a); // 11
    //         return a;
    //     }
    //     func(); // 11
    //     console.log("a", a); // 11
    // }

    // var result = fn();
    // console.log("result", result); // undefined

    /* function fn() {
        var a = 10; // 10 => 11
        console.log("a", a); // 10

        function func() {
            a++;
            console.log("a", a); // 11
            return a;
        }
        return func(); // 11  返回 func的执行结果 => 11

    }

    var result = fn();
    console.log("result", result); // 11 */



</script>
<script>
    // 闭包
    // 有权访问另一个函数作用域中变量的函数
    // 简单的说: 一个函数(fn)在执行过程中返回了另一个函数(func),该函数(func)可以访问父作用域(fn)中的变量

    // 如何形成闭包?
    // 1. 函数在执行过程返回了另一个函数(引用类型) (也可以是对象或数组等引用类型 => 包含函数)
    // 2. 返回的函数中使用了父作用域的变量
    // 3. 在函数的外部,有变量来引用 引用类型


    // 闭包的优缺点
    // 优点:
    // 1. 减少全局变量的使用   
    // 2. 被引用的父作用域不会被销毁 => 一直被子函数的作用域链引用 => 数据不会被释放(记录变化)
    // 3. 可以在函数外部访问函数内容的数据

    // 缺点:
    // 1. 数据在函数中一直被引用 => 得不到释放 => 占内存 
    // 2. 频繁的使用闭包 可能导致内存泄露 
    // 3. 可以在函数外部访问函数内容的数据 => 数据不安全

    /* function fn() {
        var a = 10; // 10 => 11  => 12
        console.log("fn执行", a); // 10

        function func() {
            a++;
            console.log("func执行", a);  // 11
            return a;
        }

        return func;  // 返回函数func (并没有调用)
    }

    var result = fn(); //  result = func   => 浅复制  result和func引用同一片内存空间 
    console.log("result", result);

    // 调用result => 调用func
    var res1 = result(); // 11
    console.log(res1);

    var res1 = result(); // 12
    console.log(res1); */



    function fn() {
        var a = 10;
        console.log("fn执行", a); // 10

        return { // 返回对象
            add: function () {
                a++;
                return a;
            },
            reduce: function () {
                a--;
                return a;
            },
            get() {
                return a;
            },
            set(val) {
                a = val;
                return a;
            }
        };
    }

    var result = fn(); //  result = obj   => 浅复制  result和obj引用同一片内存空间(包含的相关的函数) 
    console.log("result", result);

    var res1 = result.add(); // 11 
    console.log(res1);

    var res2 = result.add(); // 12
    console.log(res2);

    var res3 = result.reduce();
    console.log(res3);

    var res4 = result.set(100);
    console.log(res4);

    var res5 = result.add();
    console.log(res5)

    var res6 = result.get();
    console.log(res6);






</script>

</html>